home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / Resources / CutePDF 2.3 / converter.exe / GNUGS / PDFWRITE.PS < prev    next >
Text File  |  2002-02-23  |  8KB  |  284 lines

  1. %    Copyright (C) 1999, 2000, 2001 Aladdin Enterprises.  All rights reserved.
  2. % This software is provided AS-IS with no warranty, either express or
  3. % implied.
  4. % This software is distributed under license and may not be copied,
  5. % modified or distributed except as expressly authorized under the terms
  6. % of the license contained in the file LICENSE in this distribution.
  7. % For more information about licensing, please refer to
  8. % http://www.ghostscript.com/licensing/. For information on
  9. % commercial licensing, go to http://www.artifex.com/licensing/ or
  10. % contact Artifex Software, Inc., 101 Lucas Valley Road #110,
  11. % San Rafael, CA  94903, U.S.A., +1(415)492-9861.
  12.  
  13. % $Id: pdfwrite.ps,v 1.7.2.1 2002/02/22 19:45:55 ray Exp $
  14. % Writer for transmuting PDF files.
  15.  
  16. % NOTES:
  17. % We do editing by replacing objects (in the cache) and then doing a
  18. %   simple recursive walk with object renumbering.
  19. % Free variables:
  20. %   RMap [per input file] (dict): input_obj# => output_obj#
  21. %   PDFfile (file): current input file
  22. %   OFile (file): current output file
  23. %   XRef (dict): output_obj# => output_file_pos
  24. %   ToWrite: 0..N-1 => [obj# gen#]
  25.  
  26. /.setlanguagelevel where { pop 2 .setlanguagelevel } if
  27. .currentglobal true .setglobal
  28.  
  29. /PDEBUG where { pop } { /PDEBUG false def } ifelse
  30.  
  31. % ================ Object mapping ================ %
  32.  
  33. % Initialize the object number and location map.
  34. /omapinit {        % - omapinit -
  35.   /RMap 100 dict def
  36.   /XRef 100 dict def
  37.   PDEBUG { (omapinit) = } if
  38. } def
  39.  
  40. % Map an object number.
  41. /omapnew {        % <oldobj#> omap <newobj#> <isnew>
  42.   RMap 1 index .knownget {
  43.     exch pop false
  44.   } {
  45.     PDEBUG { (omap\() print dup =only } if
  46.     RMap dup length 1 add 2 index exch dup 5 1 roll put pop true
  47.     PDEBUG { (\) = ) print 1 index = } if
  48.   } ifelse
  49. } def
  50. /omap {            % <oldobj#> omap <newobj#>
  51.   omapnew pop
  52. } bind def
  53.  
  54. % Save and restore the object map.
  55. % Note that currentomap either returns a copy or calls omapinit.
  56. /currentomap {        % <copy> currentomap <omap>
  57.   {
  58.     [RMap dup length dict copy XRef dup length dict copy]
  59.   } {
  60.     [RMap XRef] omapinit
  61.   } ifelse
  62. } bind def
  63. /setomap {        % <omap> setomap -
  64.   aload pop /XRef exch def /RMap exch def
  65.   PDEBUG {
  66.     (setomap: #Xref = ) print XRef length =only
  67.     (, #RMap = ) print RMap length =
  68.   } if
  69. } bind def
  70.  
  71. % ================ Writing ================ %
  72.  
  73. % ---------------- Low-level output ---------------- %
  74.  
  75. % Write a string on the output file.
  76. /ows {            % <string> ows -
  77.   OFile exch writestring
  78. } def
  79.  
  80. % ---------------- Scalars ---------------- %
  81.  
  82. % Note that the '#' character isn't legal in a name unless it is a prefix
  83. % for a hex encoded character (for PDF 1.2 and later). The following assumes
  84. % that the names are already valid PDF 1.2+ names so that  we can treat the
  85. % '#' as a legal character. The next two hex characters are already in the
  86. % set of valid name characters. PDF 1.1 and earlier allowed spaces in names
  87. % which probably wouldn't make it past the tokenizer anyway.
  88. /pdfnamechars
  89.   (!"#$&'*+,-.0123456789:;=?@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\^_`abcdefghijklmnopqrstuvwxyz|~)
  90. readonly def
  91. /pdfwritename {        % <name> pdfwritename -
  92.   (/) ows .namestring {
  93.     ( ) dup 0 4 -1 roll put
  94.     //pdfnamechars 1 index search {
  95.       pop pop pop
  96.     } {
  97.       pop 0 get 256 add 16 =string cvrs
  98.       dup 0 (#) 0 get put
  99.     } ifelse ows
  100.   } forall
  101. } def
  102.  
  103. % ---------------- Composite objects ---------------- %
  104.  
  105. /pdfwriteprocs mark
  106.   /resolveR { pdfwriteref }
  107.   /O { pdfwritenewref }
  108. .dicttomark readonly def
  109. /pdfwritearray {    % <array> pdfwritearray -
  110.   dup xcheck {
  111.     aload pop //pdfwriteprocs exch get exec
  112.   } {
  113.     % Because of a bug in Acrobat's parser for linearization parameters,
  114.     % we have to include some whitespace after the opening [ (!).
  115.     ([ ) ows { pdfwritevalue (\n) ows } forall (]) ows
  116.   } ifelse
  117. } def
  118.  
  119. /pdfwritedict {        % <dict> pdfwritedict -
  120.   dup xcheck {
  121.     pdfwritestream
  122.   } {
  123.     (<<) ows {
  124.       exch pdfwritevalue ( ) ows pdfwritevalue (\n) ows
  125.     } forall (>>) ows
  126.   } ifelse
  127. } def
  128.  
  129. % ---------------- References ---------------- %
  130.  
  131. /pdfwritenewref {    % <newobj#> pdfwritenewref -
  132.   OFile exch write=only ( 0 R) ows
  133. } def
  134.  
  135. /pdfwriteref {        % <obj#> <gen#> pdfwriteref -
  136.   1 index omapnew {
  137.     ToWrite dup length 5 -2 roll 2 packedarray put
  138.   } {
  139.     exch pop exch pop
  140.   } ifelse
  141.   pdfwritenewref
  142. } def
  143.  
  144. /pdfcopystring 200 string def
  145. /pdfwritestream {    % <streamdict> pdfwritestream -
  146.     % Remove File, FilePosition, and StreamKey;
  147.     % optimize by replacing an indirect Length.
  148.   dup dup length dict copy
  149.     % Stack: origdict dict
  150.   dup /File undef dup /FilePosition undef dup /StreamKey undef
  151.   dup /Length get dup oforce ne {
  152.     dup /Length 2 copy oget put
  153.   } if
  154.   exch dup /File get dup 3 -1 roll /FilePosition get setfileposition
  155.   pdfcopystream
  156. } def
  157.  
  158. % We put copying the stream contents in separate procedures so that we
  159. % can replace this function if desired.
  160. /pdfcopybytes {        % <fromfile> <tofile> <length> pdfcopybytes -
  161.   {
  162.     dup 0 eq { exit } if
  163.     //pdfcopystring 0 2 index 2 index length .min getinterval
  164.     3 index exch readstring 3 1 roll
  165.     3 index 1 index writestring length sub exch not { exit } if
  166.   } loop pop pop pop
  167. } def
  168. /pdfcopystream {    % <newstreamdict> <file> pdfcopystream -
  169.             %   (file has been positioned)
  170.   1 index pdfwritevalue (stream\n) ows
  171.   exch /Length get OFile exch pdfcopybytes
  172.   (endstream) ows
  173. } def
  174.  
  175. % ---------------- General values/objects ---------------- %
  176.  
  177. /pdfwritetypes mark
  178.     % Scalars
  179.   /nulltype { pop (null) ows }
  180.   /integertype { =string cvs ows }
  181.   /booleantype 1 index
  182.   /realtype { OFile exch write===only }
  183.   /stringtype 1 index
  184.   /nametype { pdfwritename }
  185.     % Composite/reference objects
  186.   /arraytype { pdfwritearray }
  187.   /packedarraytype 1 index
  188.   /dicttype { pdfwritedict }
  189. .dicttomark readonly def
  190.  
  191. /pdfwritevalue {    % <obj> pdfwritevalue -
  192.   PDEBUG { (****Writing: ) print dup === flush } if
  193.   //pdfwritetypes 1 index type get exec
  194. } def
  195.  
  196. % We make pdfwriteobjdef a separate procedure for external use.
  197. /pdfwriteobjheader {    % <newobj#> pdfwriteobjheader -
  198.   XRef 1 index OFile .fileposition put
  199.   PDEBUG { (XRef\() print dup =only (\) = ) print XRef 1 index get = } if
  200.   OFile exch write=only ( 0 obj\n) ows
  201. } def
  202. /pdfwriteobjdef {    % <newobj#> <value> pdfwriteobjdef -
  203.   exch pdfwriteobjheader
  204.   pdfwritevalue (\nendobj\n) ows
  205. } def
  206. /pdfwriteobj {        % <obj#> <gen#> pdfwriteobj -
  207.   1 index exch resolveR exch omap exch pdfwriteobjdef
  208. } def
  209.  
  210. % ---------------- File-level entities ---------------- %
  211.  
  212. % Write a PDF file header.
  213. % Free variables: OFile, PDFversion.
  214. /pdfwriteheader {    % - pdfwriteheader -
  215.   (%PDF-) ows OFile PDFversion write=
  216.   (%\347\363\317\323\n) ows
  217. } bind def
  218.  
  219. % Write a cross-reference table and trailer.
  220. /pdfwritexref {        % <firstobj#> <#objs> pdfwritexref -
  221.   (xref\n) ows
  222.   OFile 2 index write=only ( ) ows OFile 1 index write=
  223.   1 index add 1 sub 1 exch {
  224.     dup 0 eq {
  225.       pop (0000000000 65535 f \n) ows
  226.     } {
  227.       XRef exch get 1000000000 add =string cvs
  228.       dup 0 (0) 0 get put
  229.       ows ( 00000 n \n) ows
  230.     } ifelse
  231.   } for
  232. } bind def
  233. /pdfwritetrailer {    % <trailer> pdfwritetrailer -
  234.   (trailer\n) ows pdfwritevalue (\n) ows
  235. } bind def
  236. /pdfwritestartxref {    % <startpos> pdfwritestartxref -
  237.   (startxref\n) ows OFile exch write=
  238.   (%%EOF\n) ows
  239. } bind def
  240.  
  241. % ================ Top-level control ================ %
  242.  
  243. /pdfwrite {        % <file> <trailer> pdfwrite -
  244.   10 dict begin
  245.   /trailer exch def
  246.   /OFile exch def
  247.   /ToWrite 100 dict def
  248.   omapinit
  249.  
  250.     % Write the PDF file header.
  251.  
  252.   pdfwriteheader
  253.  
  254.     % Write the objects.
  255.  
  256.   trailer {
  257.     exch pop dup xcheck {    % The only executable objects are references.
  258.       aload pop pop pdfwriteobj
  259.     } {
  260.       pop
  261.     } ifelse
  262.   } forall
  263.     % Walk the object graph.
  264.   {
  265.     ToWrite dup length dup 0 eq { pop pop exit } if
  266.     1 sub 2 copy get 3 1 roll undef aload pop pdfwriteobj
  267.   } loop
  268.  
  269.     % Write the xref table and trailer.
  270.  
  271.   /xref OFile fileposition def
  272.   0 XRef length 1 add pdfwritexref
  273.   trailer dup length 1 add dict copy
  274.   dup /Size XRef length 1 add put pdfwritetrailer
  275.   xref pdfwritestartxref
  276.  
  277.   end
  278. } def
  279.  
  280. .setglobal
  281.